#include "SIN32.h"
#include "Managers.h"
#include "boomerang.h"
#define __NATIVE__ //Native Program Compile Directive.
#define __DEBUG__ //stores debug output to the DEBUG_STREAM File in Sin32.exe
#define SIN_THREAD_MAX 4
static HANDLE SyncEvent = INVALID_HANDLE_VALUE;
static HANDLE NotifyEvent = INVALID_HANDLE_VALUE;
static HANDLE MessageDataBuffer = INVALID_HANDLE_VALUE;
LIST_ENTRY ClientListHead = {0};
ProcessManager PManager;
ThreadManager TManager;
SIN_CLIENT_ENTRY *SinSrvLocateClientByPid(HANDLE UniqueProcess)
{
	SIN_CLIENT_ENTRY *TempTable = {0};
	if(IsListEmpty(&ClientListHead))
	{
		return TempTable;
	}
	TempTable = (SIN_CLIENT_ENTRY*)ClientListHead.Flink;
	do
	{
		if(TempTable->ProcessId == UniqueProcess)
		{
			return TempTable;
		}
		TempTable = (TempTable->ClientList.Flink == (LIST_ENTRY*)&ClientListHead) ? (SIN_CLIENT_ENTRY*)TempTable->ClientList.Flink : 0;
	}
	while(TempTable);
	TempTable = 0;
	return TempTable;
}
BOOLEAN SinSrvCleanClientTable(HANDLE UniqueProcess)
{
	SIN_CLIENT_ENTRY *TempTable = {0};
	TempTable = SinSrvLocateClientByPid(UniqueProcess);
	if(TempTable)
	{
		return RemoveEntryList(&TempTable->ClientList);
	}
	return false;
}
bool SinSrvIsClientEntryEmpty(SIN_CLIENT_ENTRY *ClientEntry)
{
	if(ClientEntry->ThreadId && ClientEntry->ProcessId && ClientEntry->ClientPort && ClientEntry->ServerThread)
	{
		return false;
	}
	return true;
}
__forceinline void InitializeSinApiMessage(SIN_API_MESSAGE *ph,USHORT len,LPC_TYPE type,SIN_API_TYPE apitype)
{
    ph->Header.u1.s1.TotalLength    = len;
    ph->Header.u1.s1.DataLength     = len - sizeof(PORT_MESSAGE); 
    ph->Header.u2.s2.Type           = (USHORT)(type);
    ph->Header.u2.s2.DataInfoOffset = 0;                                  
	ph->ApiType			   = (ULONG)(apitype);
}	
void SinSrvMain()
{
	SIN_API_MESSAGE Message = {0};
	SIN_CLIENT_ENTRY ConnectionInfo = {0};
	UNICODE_STRING Unicode = {0};
#ifdef __DEBUG__
	UNICODE_STRING UniDbg = {0};
	PVOID DbgModule = 0;
#endif
	OBJECT_ATTRIBUTES oa = {0};
	NTSTATUS Status = 0;
	SECURITY_DESCRIPTOR SecDesc = {0};
	LARGE_INTEGER TIMEOUT = {INFINITE};
	HANDLE TargetProcess = INVALID_HANDLE_VALUE;
	HANDLE SectionHandle = INVALID_HANDLE_VALUE;
	HANDLE LpcPortHandle = INVALID_HANDLE_VALUE;
	RTL_CRITICAL_SECTION SinCrit = {0};
	CLIENT_ID ClientId = {0};
	oa.Length = sizeof(OBJECT_ATTRIBUTES);
	__try
	{
		MessageDataBuffer = RtlCreateHeap(HEAP_GROWABLE|HEAP_ZERO_MEMORY,0,0,0x4096,0,0);
		ConnectionInfo = *(SIN_CLIENT_ENTRY*)Native_AllocateHeap(MessageDataBuffer,sizeof(SIN_CLIENT_ENTRY),MEMORY_ALLOCATION_ALIGNMENT);
		InitializeListHead(&ClientListHead);
		Status = RtlCreateSecurityDescriptor(&SecDesc,1);
		if(!NT_SUCCESS(Status))
		{
#ifdef __DEBUG__
			RtlInitUnicodeString(&UniDbg,L"Failed Creating Security Descriptor:");
			goto Dbg;
#endif
		}
		Status = RtlSetDaclSecurityDescriptor(&SecDesc,true,(PACL)NULL,false);
		if(!NT_SUCCESS(Status))
		{
#ifdef __DEBUG__
			RtlInitUnicodeString(&UniDbg,L"Fail Setting Dacl on Descriptor:");
			goto Dbg;
#endif
		}
		RtlInitUnicodeString(&Unicode,LpcCommEventName);
		InitializeObjectAttributes(&oa,&Unicode,OBJ_KERNEL_HANDLE,0,&SecDesc);
		if(!NT_SUCCESS(Status))
		{
#ifdef __DEBUG__
			RtlInitUnicodeString(&UniDbg,L"Setting acl Unsuccessful Status:");
			goto Dbg;
#endif
		}
		Status = NtCreateEvent(&NotifyEvent,EVENT_ALL_ACCESS,&oa,NotificationEvent,TRUE);
		if(!NT_SUCCESS(Status))
		{
#ifdef __DEBUG__
			RtlInitUnicodeString(&UniDbg,L"NtCreateEvent Status: ");
			goto Dbg;
#endif
		}
		RtlInitUnicodeString(&Unicode,LpcSyncEventName);
		InitializeObjectAttributes(&oa,&Unicode,OBJ_KERNEL_HANDLE,0,&SecDesc);
		Status = NtCreateEvent(&SyncEvent,EVENT_ALL_ACCESS,&oa,SynchronizationEvent,TRUE);
		if(!NT_SUCCESS(Status))
		{
#ifdef __DEBUG__
			RtlInitUnicodeString(&UniDbg,L"NtCreateEvent Status: ");
			goto Dbg;
#endif
		}
		//Status = RtlAdjustPrivilege(16L,false,false,0);
		if(!NT_SUCCESS(Status))
		{
#ifdef	__DEBUG__
			RtlInitUnicodeString(&UniDbg,L"Failing removing Privilege ");
			goto Dbg;
#endif
		}
		
		TIMEOUT.LowPart = 0x4096;
		//Create The Section that will be used for Client/Server Communication
		Status = NtCreateSection(&SectionHandle,SECTION_ALL_ACCESS,NULL,&TIMEOUT,PAGE_EXECUTE_READWRITE,SEC_COMMIT,0);
		if(!NT_SUCCESS(Status))
		{
#ifdef __DEBUG__
			RtlInitUnicodeString(&UniDbg,L"NtCreateSection Status: ");
			goto Dbg;		
#endif
		}
		oa.Length = sizeof(OBJECT_ATTRIBUTES);
		RtlInitUnicodeString(&Unicode, LpcPortName);
        InitializeObjectAttributes(&oa, &Unicode,OBJ_KERNEL_HANDLE, NULL,0);
		//Create The Port used for Listening.
		Status = NtCreatePort(&LpcPortHandle,&oa,0,sizeof(SIN_API_MESSAGE),4*sizeof(SIN_API_MESSAGE));
		if(!NT_SUCCESS(Status))
		{
#ifdef __DEBUG__
			RtlInitUnicodeString(&UniDbg,L"NtCreatePort Status: ");
			goto Dbg;
#endif
		}
		RtlInitializeCriticalSection(&SinCrit);
WaitClients:
		Status = NtListenPort(LpcPortHandle, (PORT_MESSAGE*)&Message);
        if(!NT_SUCCESS(Status))
		{
#ifdef __DEBUG__
			RtlInitUnicodeString(&UniDbg,L"NtListenPort Status: ");
			goto Dbg;
#endif
		}
		if(Message.Header.u2.s2.Type == LPC_CONNECTION_REQUEST)
		{
			
			RtlTryEnterCriticalSection(&SinCrit);
			if(SinSrvIsClientEntryEmpty(&ConnectionInfo)== true)
			{
				ConnectionInfo.ProcessId = Message.Header.ClientId.UniqueProcess;
				ConnectionInfo.ThreadId = Message.Header.ClientId.UniqueThread;
				InsertHeadList(&ClientListHead,(PLIST_ENTRY)&ConnectionInfo.ClientList);
			}
			else
			{
				ConnectionInfo.ClientList.Flink = (LIST_ENTRY*)Native_AllocateHeap(MessageDataBuffer,sizeof(SIN_CLIENT_ENTRY),MEMORY_ALLOCATION_ALIGNMENT);
				ConnectionInfo = *(SIN_CLIENT_ENTRY*)ConnectionInfo.ClientList.Flink;
				if(&ConnectionInfo)
				{
					ConnectionInfo.ProcessId = Message.Header.ClientId.UniqueProcess;
					ConnectionInfo.ThreadId = Message.Header.ClientId.UniqueThread;
					InsertHeadList(&ClientListHead,(PLIST_ENTRY)&ConnectionInfo.ClientList);
				}
				else
				{
					ConnectionInfo = *(SIN_CLIENT_ENTRY*)RtlAllocateHeap(MessageDataBuffer,HEAP_ZERO_MEMORY,sizeof(SIN_CLIENT_ENTRY));
					ConnectionInfo.ProcessId = Message.Header.ClientId.UniqueProcess;
					ConnectionInfo.ThreadId = Message.Header.ClientId.UniqueThread;
					InsertHeadList(&ClientListHead,(PLIST_ENTRY)&ConnectionInfo.ClientList);
				}
			}
			ConnectionInfo.ServerView.Length         = sizeof(PORT_VIEW);
			ConnectionInfo.ServerView.SectionHandle  = SectionHandle;
			ConnectionInfo.ServerView.SectionOffset  = 0;
			ConnectionInfo.ServerView.ViewSize       = 0x4096;
			ConnectionInfo.ServerView.ViewBase		  = 0;
			ConnectionInfo.ServerView.ViewRemoteBase = 0;
			ConnectionInfo.ClientView.Length         = sizeof(REMOTE_PORT_VIEW);
			Status = NtAcceptConnectPort(&ConnectionInfo.ClientPort,NULL,(PORT_MESSAGE*)&Message,TRUE,&ConnectionInfo.ServerView,&ConnectionInfo.ClientView);		
			if(!NT_SUCCESS(Status))
			{
#ifdef __DEBUG__
				RtlInitUnicodeString(&UniDbg,L"NtAcceptConnectPort Status: ");
				goto Dbg;
#endif	
			}
			Status = NtCompleteConnectPort(ConnectionInfo.ClientPort);
			if(!NT_SUCCESS(Status))
			{
#ifdef __DEBUG__
				RtlInitUnicodeString(&UniDbg,L"NtCompleteConnectPort Status :");
				goto Dbg;
#endif
			}
			Status = NtResetEvent(NotifyEvent,0);
			Status = NtResetEvent(SyncEvent,0);
			if(!NT_SUCCESS(RtlCreateUserThread(NtCurrentProcess(),0,true,0,0,0,(PUSER_THREAD_START_ROUTINE)MessageHandler,(PVOID)&ConnectionInfo,&ConnectionInfo.ServerThread,&ClientId)))
			{
#ifdef __DEBUG__
				RtlInitUnicodeString(&UniDbg,L"RtlCreateUserThread Status :");
				goto Dbg;
#endif
			}
			Status = NtResumeThread(ConnectionInfo.ServerThread,0);
			if(!NT_SUCCESS(Status))
			{
#ifdef __DEBUG__
				RtlInitUnicodeString(&UniDbg,L"NtResumeThread Status :");
				goto Dbg;
#endif
			}
			RtlLeaveCriticalSection(&SinCrit);
		}
		goto WaitClients;
Dbg:		
	DbgPrint("%wZ %8x",UniDbg.Buffer,Status);
	RtlInitUnicodeString(&UniDbg,L"SinSrv");
	LdrGetDllHandle(0,0,&UniDbg,&DbgModule);
	LdrUnloadDll(DbgModule);
	}
	__except(1)
	{
		if(SyncEvent && NotifyEvent)
		{
			NtClose(SyncEvent);
			NtClose(NotifyEvent);
		}
		if(SectionHandle != INVALID_HANDLE_VALUE)
		{
			NtClose(SectionHandle);
		}
		if(LpcPortHandle != INVALID_HANDLE_VALUE)
		{
			NtClose(LpcPortHandle);
		}
		if(ConnectionInfo.ClientPort != INVALID_HANDLE_VALUE)
		{
			NtClose(ConnectionInfo.ClientPort);
		}
		RtlInitUnicodeString(&UniDbg,L"Sin32");
		LdrGetDllHandle(0,0,&UniDbg,&DbgModule);
		LdrUnloadDll(DbgModule);
	}
}
void SinInitBoomerang()
{	
	Boomerang *CmdInterface;
	CmdInterface->commandLine();
}
void Main()
{
	TManager.CreateThisThread(false,false,(HANDLE)-1,(PVOID*)SinSrvMain,0);
	TManager.CreateThisThread(false,true,(HANDLE)-1,(PVOID*)SinInitBoomerang,0);
}

BOOLEAN SinInjectClient(SIN_API_MESSAGE *ApiRecvMessage)
{
	SIN_REQUEST_INJECT_CLIENT *ReqInjectClient = {0};
	SIN_CLIENT_ENTRY *ThisEntry = 0;
	UNICODE_STRING Unicode = {0};
	ANSI_STRING Ansi = {0};
	CLIENT_ID ClientId = {0};
	OBJECT_ATTRIBUTES oa = {0};
	NTSTATUS Status = 0;
	ULONG Reused = 0;
	PVOID HandlerLocation = 0;
	ReqInjectClient = (SIN_REQUEST_INJECT_CLIENT*)&ApiRecvMessage->ApiInfo.ReqInjectClient;
	RtlInitAnsiString(&Ansi,ReqInjectClient->ProcessName);
	RtlAnsiStringToUnicodeString(&Unicode,&Ansi,true);
	ClientId.UniqueProcess = GetPidByName(Unicode.Buffer);
	ThisEntry = SinSrvLocateClientByPid(ClientId.UniqueProcess);
	if(!ThisEntry)
	{
		ThisEntry = (SIN_CLIENT_ENTRY*)RtlAllocateHeap(MessageDataBuffer,0,sizeof(SIN_CLIENT_ENTRY));
	}
	ThisEntry->ProcessId = ClientId.UniqueProcess;
	InsertTailList(&ClientListHead,(PLIST_ENTRY)&ThisEntry->ClientList);
	ClientId.UniqueThread = 0;
	if(NT_SUCCESS(RtlAdjustPrivilege(20L,true,0,(PBOOLEAN)&Reused)))
	{
		InitializeObjectAttributes(&oa,0,0,0,0);
		if(NT_SUCCESS(NtOpenProcess(&ThisEntry->Process,PROCESS_ALL_ACCESS,&oa,&ClientId)))
		{
			if(NT_SUCCESS(RtlAdjustPrivilege(20L,false,0,(PBOOLEAN)&Reused)))
			{
				RtlInitAnsiString(&Ansi,"C:\\WINDOWS\\System32\\SinSrvClient.dll");
				InitializeObjectAttributes(&oa,0,0,0,0);
				if(NT_SUCCESS(Status = NtAllocateVirtualMemory(ThisEntry->Process,&HandlerLocation,0,(PSIZE_T)&Ansi.Length,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE)))
				{
					if(NT_SUCCESS(NtWriteVirtualMemory(ThisEntry->Process,HandlerLocation,(PVOID)Ansi.Buffer,(ULONG)Ansi.Length,&Reused)))
					{
						Reused = *(ULONG*)Native_GetApi(L"kernel32.dll","LoadLibraryA");
						if(NT_SUCCESS(RtlCreateUserThread(ThisEntry->Process,0,false,0,0,0,(PUSER_THREAD_START_ROUTINE)Reused,HandlerLocation,&ThisEntry->ThreadId,&ClientId)))
						{
							if(NT_SUCCESS(NtFreeVirtualMemory(ThisEntry->Process,&HandlerLocation,(PSIZE_T)&Ansi.Length,MEM_RELEASE)))
							{
								Reused = (ULONG)Native_GetApi(L"SinSrvClient.dll","SinSrvClientConnectServer");
								if(NT_SUCCESS(RtlCreateUserThread(ThisEntry->Process,0,false,0,0,0,(PUSER_THREAD_START_ROUTINE)Reused,0,&ThisEntry->ThreadId,&ClientId)))
								{
									return TRUE;
								}
							}
						}
					}
				}
			}
		}
	}
	return FALSE;
}
BOOLEAN SinInjectDll(SIN_API_MESSAGE *ApiRecvMessage)
{
	SIN_CLIENT_ENTRY *ThisEntry = {0};
	SIN_REQUEST_INJECT_DLL *ReqInjectDll = {0};
	PVOID HandlerLocation = 0;
	UNICODE_STRING Unicode = {0};
	ANSI_STRING Ansi = {0};
	OBJECT_ATTRIBUTES oa = {0};
	CLIENT_ID ClientId = {0};
	void *Reused = 0;
	ULONG Size = 0;
	ReqInjectDll = (SIN_REQUEST_INJECT_DLL*)&ApiRecvMessage->ApiInfo.ReqDllInject;
	ThisEntry = SinSrvLocateClientByPid(ApiRecvMessage->Header.ClientId.UniqueProcess);
	if(!ThisEntry)
	{
		ThisEntry = (SIN_CLIENT_ENTRY*)RtlAllocateHeap(MessageDataBuffer,0,sizeof(SIN_CLIENT_ENTRY));
	}
	RtlInitAnsiString(&Ansi,ReqInjectDll->ProcessName);
	if(NT_SUCCESS(RtlAnsiStringToUnicodeString(&Unicode,&Ansi,false)))
	{
		ClientId.UniqueProcess = GetPidByName(Unicode.Buffer);
		ClientId.UniqueThread = 0;
		InitializeObjectAttributes(&oa,0,0,0,0);
		if(NT_SUCCESS(NtOpenProcess(&ThisEntry->Process,PROCESS_ALL_ACCESS,&oa,&ClientId)))
		{
			RtlInitAnsiString(&Ansi,ReqInjectDll->DllPath);
			if(NT_SUCCESS(RtlAnsiStringToUnicodeString(&Unicode,&Ansi,false)))
			{
				InitializeObjectAttributes(&oa,0,0,0,0);
				if(NT_SUCCESS(NtAllocateVirtualMemory(ThisEntry->Process,&HandlerLocation,0,(PSIZE_T)&Ansi.Length,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE)))
				{
					if(NT_SUCCESS(NtWriteVirtualMemory(ThisEntry->Process,HandlerLocation,(PVOID)Ansi.Buffer,(ULONG)Ansi.Length,&Size)))
					{
						Reused = (void*)Native_GetApi(L"kernel32.dll","LoadLibraryA");
						if(NT_SUCCESS(RtlCreateUserThread(ThisEntry->Process,0,false,0,0,0,(PUSER_THREAD_START_ROUTINE)Reused,HandlerLocation,&ThisEntry->ThreadId,&ClientId)))
						{
							if(NT_SUCCESS(NtFreeVirtualMemory(ThisEntry->Process,&HandlerLocation,(PSIZE_T)&Ansi.Length,MEM_RELEASE)))
							{
								return TRUE;
							}
						}
					}
				}
			}
		}
	}
	return FALSE;
}
BOOLEAN SinSrvInjectVeh(SIN_API_MESSAGE* ApiRecvMessage)
{
	SIN_REQUEST_VEH_TAKEOVER *ReqVehHook = {0};
	SIN_CLIENT_ENTRY *ThisEntry = {0};
	VEH_HIJACK_SETUP HijackInfo = {0};
	MEMORY_BASIC_INFORMATION mbi = {0};
	UNICODE_STRING Unicode = {0};
	ANSI_STRING Ansi = {0};
	CLIENT_ID ClientId = {0};
	PVOID HandlerLocation = 0;
	PVOID HookLocation = 0;
	ULONG Size = 0;
	ULONG Reused = 0;
	ReqVehHook = (SIN_REQUEST_VEH_TAKEOVER*)&ApiRecvMessage->ApiInfo.ReqVehHook;
	if(Sinject::SinSrvSetupVeHijack(&HijackInfo))
	{
		if(ReqVehHook->HandleExceptionType == 0)
		{
			RtlInitAnsiString(&Ansi,ReqVehHook->ProcessName);
			if(NT_SUCCESS(RtlAnsiStringToUnicodeString(&Unicode,&Ansi,false)))
			{
				ClientId.UniqueProcess = GetPidByName(Unicode.Buffer);
				ThisEntry = SinSrvLocateClientByPid(ClientId.UniqueProcess);
				if(!ThisEntry)
				{
					ThisEntry = (SIN_CLIENT_ENTRY*)RtlAllocateHeap(MessageDataBuffer,0,sizeof(SIN_CLIENT_ENTRY));
					ThisEntry->ProcessId = ClientId.UniqueProcess;
					InsertHeadList(&ClientListHead,(PLIST_ENTRY)&ThisEntry->ClientList);
				}
				ClientId.UniqueThread = 0;
				if(!NT_SUCCESS(NtOpenProcess(&ThisEntry->Process,PROCESS_ALL_ACCESS,0,&ClientId)))
				{
					return FALSE;
				}
				Size = GetFunctionLength(Sinject::HookHandler);
				if(NT_SUCCESS(NtAllocateVirtualMemory(ThisEntry->Process,&HandlerLocation,0,(SIZE_T*)Size,MEM_COMMIT,PAGE_EXECUTE_READWRITE)))
				{
					if(NT_SUCCESS(NtWriteVirtualMemory(ThisEntry->Process,HandlerLocation,HookHandler,Size,&Reused)))
					{
						ThisEntry->HookInfo.Handler = HijackInfo.VectoredHandler = HandlerLocation;
						if(ThisEntry->HookInfo.NumTargets == 0)
						{
							if(NT_SUCCESS(NtWriteVirtualMemory(ThisEntry->Process,HandlerLocation,(PVOID)ReqVehHook->TargetFunc,sizeof(ULONG),&Reused)))
							{
								ThisEntry->HookInfo.NumTargets++;
								if(NT_SUCCESS(NtWriteVirtualMemory(ThisEntry->Process,((PVOID)((ULONG)HandlerLocation+sizeof(ULONG)*10)),(PVOID)ReqVehHook->HookFunc,sizeof(ULONG),&Reused)))
								{
									ThisEntry->HookInfo.NumHooks++;
									goto Install;
								}
							}
						}
					}
				}
				return FALSE;
			}
			else
			{
				if(NT_SUCCESS(NtWriteVirtualMemory(ThisEntry->Process,((PVOID)((ULONG)ThisEntry->HookInfo.Handler+sizeof(ULONG)*ThisEntry->HookInfo.NumTargets)),(PVOID)ReqVehHook->TargetFunc,sizeof(ULONG),&Reused)))
				{
					ThisEntry->HookInfo.NumTargets++;
					if(NT_SUCCESS(NtWriteVirtualMemory(ThisEntry->Process,((PVOID)((ULONG)ThisEntry->HookInfo.Handler+sizeof(ULONG)*10+sizeof(ULONG)*ThisEntry->HookInfo.NumHooks)),(PVOID)ReqVehHook->HookFunc,sizeof(ULONG),&Reused)))
					{
						ThisEntry->HookInfo.NumHooks++;
						return TRUE;
					}
				}
				return FALSE;
			}
Install:
			Size = GetFunctionLength(Sinject::SinSrvSetupVeHijack);
			if(NT_SUCCESS(NtAllocateVirtualMemory(ThisEntry->Process,&HookLocation,0,(SIZE_T*)Size,MEM_COMMIT,PAGE_EXECUTE_READWRITE)))
			{
				if(NT_SUCCESS(NtWriteVirtualMemory(ThisEntry->Process,HookLocation,SinSrvHijackVEH,Size,&Reused)))
				{
					if(NT_SUCCESS(NtQueryVirtualMemory(ThisEntry->Process,(PVOID)ReqVehHook->TargetFunc,MemoryBasicInformation,&mbi,sizeof(mbi),0)))
					{
						if(mbi.AllocationProtect & PAGE_NOACCESS)
						{
							if(NT_SUCCESS(RtlCreateUserThread(ThisEntry->Process,0,false,0,0,0,(PUSER_THREAD_START_ROUTINE)(void*)((ULONG)HandlerLocation+(sizeof(ULONG)*10)*3),&HijackInfo,&ThisEntry->ThreadId,&ClientId)))
							{
								return TRUE;
							}
						}
						else
						{
							if(NT_SUCCESS(NtProtectVirtualMemory(ThisEntry->Process,(PVOID*)&ReqVehHook->TargetFunc,&Size,PAGE_NOACCESS,&Reused)))
							{
								if(NT_SUCCESS(RtlCreateUserThread(ThisEntry->Process,0,false,0,0,0,(PUSER_THREAD_START_ROUTINE)((ULONG)HandlerLocation+(sizeof(ULONG)*10)*3),&HijackInfo,&ThisEntry->ThreadId,&ClientId)))
								{
									return TRUE;
								}
							}	 
						}
					}
				}
			}
		}
		return FALSE;
	}
	else//int3Hooks...
	{
		return FALSE;
	}
}

void MessageHandler(SIN_CLIENT_ENTRY *BaseMessage)
{
	void *ReplyMessage = 0;
	void *RecvMessage = 0;
	void *ReqData = 0;
	void *HookLocation = 0;
	void *HandlerLocation = 0;
	NTSTATUS Status = 0;
	UNICODE_STRING Unicode = {0};
	ANSI_STRING Ansi = {0};
	OBJECT_ATTRIBUTES oa = {0};
	SIN_API_MESSAGE ApiReplyMessage = {0};
	SIN_API_MESSAGE ApiRecvMessage = {0};
	SIN_CLIENT_ENTRY *ThisEntry = {0};
	CLLHook TargetForHook = {0};
	THREAD_INFORMATION ClientThreads = {0};
	BYTE FindThis[] = {0x83,0xc6,0,0x04};
	__try
	{
		ReplyMessage = RtlAllocateHeap(MessageDataBuffer,HEAP_ZERO_MEMORY,sizeof(SIN_API_MESSAGE));
		RecvMessage = RtlAllocateHeap(MessageDataBuffer,HEAP_ZERO_MEMORY,sizeof(SIN_API_MESSAGE));
		ApiReplyMessage =*(SIN_API_MESSAGE*)ReplyMessage;
		ApiRecvMessage = *(SIN_API_MESSAGE*)RecvMessage;
WaitApiMessage:
		Status = NtReplyWaitReceivePort(BaseMessage->ClientPort,NULL,0,(PORT_MESSAGE*)&ApiRecvMessage);
		if(!NT_SUCCESS(Status))
		{
			RtlFreeHeap(MessageDataBuffer,0,RecvMessage);
			RtlFreeHeap(MessageDataBuffer,0,ReplyMessage);
			ExitThread(0);
		}
		switch( ApiRecvMessage.Header.u2.s2.Type )
		{
			case LPC_PORT_CLOSED: 
			case LPC_CLIENT_DIED:				
				RtlFreeHeap(MessageDataBuffer,0,RecvMessage);
				RtlFreeHeap(MessageDataBuffer,0,ReplyMessage);
				SinSrvCleanClientTable(BaseMessage->ProcessId);
				NtTerminateThread(BaseMessage->ServerThread,0);
			case LPC_LOST_REPLY:
				NtReplyPort(BaseMessage->ClientPort,(PORT_MESSAGE*)&ApiReplyMessage);
				goto WaitApiMessage;
			case LPC_REQUEST:
			{					
				switch(ApiRecvMessage.ApiType)
				{
					case SIN_INJECT_CLIENT:
					{
						break;
					}
					case SIN_INJECT_DLL:
					{					

						break;
					}
					/*
					case SIN_INJECT_DATA:
					{
						break;
					}
					case SIN_INJECT_CODE:
					{					
						break;					
					}
					case SIN_RUN_CODE:
					{					
						break;					
					}
					case SIN_REMOTE_HOOK:
					{					
						break;
					}*/
					case SIN_REMOTE_VEH_TAKEOVER:
					{
						break;
					}
					case SIN_SUSPEND_CLIENT:
					{
						ThisEntry = SinSrvLocateClientByPid(ApiRecvMessage.Header.ClientId.UniqueProcess);
						ClientThreads.ClientId = ApiRecvMessage.Header.ClientId;
						Status = Sinject::SuspendSiblings((ULONG)ClientThreads.ClientId.UniqueProcess ,(ULONG) ClientThreads.ClientId.UniqueThread, true,&ClientThreads);
						break;
					}
					case SIN_WAIT_SERVER:
					{						
						break;
					}
					default:
						break;
				}
			}
		}
		InitializeSinApiMessage(&ApiReplyMessage,sizeof(SIN_API_MESSAGE),LPC_NEW_MESSAGE,SIN_WAIT_SERVER);	
		ApiReplyMessage.Header = ApiRecvMessage.Header;
		memcpy(&ApiReplyMessage.ClientInfo,(void*)ThisEntry,sizeof(SIN_CLIENT_ENTRY));
		Status = NtReplyPort(BaseMessage->ClientPort,(PORT_MESSAGE*)&ApiReplyMessage);
		goto WaitApiMessage;
	}
	__except(1)
	{
		if(BaseMessage->ClientPort != INVALID_HANDLE_VALUE)
		{
			NtClose(BaseMessage->ClientPort);
		}
	}
	return;
}